#pragma once
#include<iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<cstring>
#include<netinet/in.h>
#include"Mypopen.hpp"
#include"log.hpp"
extern Log l;
std::string defaultip = "0.0.0.0";
uint16_t defaultport = 8080;
class UdpServer{
private:
public:
    UdpServer(const uint16_t port = defaultport,const std::string &ip = defaultip)
        :_port(port)
        ,_ip(ip)
    {
      IsRun = false;
    }
    void Init()
    {
        //1.创建Udp socket
        //Udp的socket是全双工的,允许同时被读写
        _socketfd = socket(AF_INET,SOCK_DGRAM,0);
        if(_socketfd < 0)
        {
            l(Fatal,"socket create error");
            exit(-1);
        }
        l(Info,"socket create suceess,socket %d",_socketfd);

       //2.bind
       struct sockaddr_in local;
       bzero(&local,sizeof(local)); //置成0
    //    local.sin_addr.s_addr = (inet_addr(_ip.c_str()));//字符串转整数
       local.sin_addr.s_addr = htonl(INADDR_ANY);
       local.sin_family = AF_INET;
       local.sin_port = htons(_port); //需要保证端口号是网络字节序列,因为该端口号是要给对方发送的

       int n = bind(_socketfd,(const struct sockaddr*)&local,sizeof(local));
       if(n < 0)
       {
         l(Fatal,"bind error!,errno: %d,err string: %s",errno,strerror(errno));
         exit(0);
       }
       l(Info,"bind suceess,bind port: %d",_port);
    }
    void Run()
    {
        IsRun = true;
        char inbuff[1024];
        while(IsRun)
        {
          struct sockaddr_in client;
          socklen_t len = sizeof(client);
          ssize_t n = recvfrom(_socketfd,inbuff,sizeof(inbuff) - 1,0,(struct sockaddr*)(&client),&len);
          if(n < 0)
          {
            l(Warning,"recvfrom error");
            continue;
          }
          // uint16_t port = ntohs(client.sin_port);
          // std::string ip = inet_ntoa(client.sin_addr);
         
          inbuff[n] = '\0';
          cout << "Server get a message: " << inbuff << endl;
          // string info = inbuff;
          //可以做安全检测，检测有没有一些重要的命令比如rm等
          
          // string echo_string = ExecuteCommand(info);
          //checkUser
          string echo_string = inbuff;
          // getline(cin,echo_string);
          sendto(_socketfd,echo_string.c_str(),echo_string.size(),0,(sockaddr*)&client,len);
        }
    }
    ~UdpServer()
    {
        close(_socketfd);
    }
private:
    bool CheckSafe(const string& str)
    {
        vector<string> v = {"rm","cp","mv","top","yum","while","top"};
        for(const auto&e:v)
        {
          if(str.find(e) != string::npos)return false;
        }
        return true;
    }
    string ExecuteCommand(const string& info)
    {
      //
      if(!CheckSafe(info))
      {
        return "dont do bad action!";
      }
      FILE* fp = Mypopen(info.c_str(),"r");
      if(fp == nullptr)
      {
        perror("popen");
        exit(0);
      }
      char buff[4096];
      string ret;
      while(1)
      {
        char* res = fgets(buff,sizeof(buff),fp);
        if(!res) break;
        string tmp = buff;
        ret += tmp;
      }
      pclose(fp); 
      return ret;
    }
private:

    int _socketfd; //网络文件描述符
    uint16_t _port; //表明服务器进程的端口号
    std::string _ip; //
    bool IsRun;
};
